January 09, 2021
숫자들과 3가지의 연산문자(+, -, *) 만으로 이루어진 연산 수식
전달받은 수식에 포함된 연산자의 우선순위를 자유롭게 재정의하여 만들 수 있는 가장 큰 숫자를 제출하는 것입니다.
두 가지 방법이 떠오는데 둘 다 스택을 사용하는 방법이다.
후위표기식을 이용한 방법으로 풀이를 시도해본다.
연산한다.
과정은 쉬운데 구현에 꽤나 힘이 들었다.
오랜만에 후위표기법을 사용해보았다.
function getCases(opers: string[]): Set<{ [operator: string]: number }> {
const cases = new Set<{ [operator: string]: number }>()
for (let i = 0; i < opers.length; i++) {
for (let j = 0; j < opers.length; j++) {
for (let k = 0; k < opers.length; k++) {
if (i !== j && j !== k && i !== k) {
cases.add({ '*': i, '-': j, '+': k })
}
}
}
}
return cases
}
const postFix = (
splittedExp: string[],
operator: { [operator: string]: number }
): number => {
const stack: string[] = []
const result = []
splittedExp.forEach(elem => {
if (!Number.isNaN(parseInt(elem))) {
result.push(parseInt(elem))
} else {
while (stack.length) {
if (operator[elem] <= operator[stack[stack.length - 1]]) {
result.push(stack.pop())
} else {
break
}
}
stack.push(elem)
}
})
while (stack.length) {
result.push(stack.pop())
}
const numStack: number[] = []
result.forEach(elem => {
if (typeof elem == 'number') {
numStack.push(elem)
} else {
const num2: number = numStack.pop()
const num1: number = numStack.pop()
switch (elem) {
case '+':
numStack.push(num1 + num2)
break
case '-':
numStack.push(num1 - num2)
break
case '*':
numStack.push(num1 * num2)
break
}
}
})
return numStack[0]
}
function solution(expression: string): number {
const operators = ['*', '+', '-']
const cases = getCases(operators)
const splittedExp = expression.split(/(\*|\-|\+)/)
let max = 0
cases.forEach(element => {
const result = Math.abs(postFix(splittedExp, element))
max = max < result ? result : max
})
return max
}
export default solution
소스코드가 길고 가독성도 좋지 않다. 리팩토링을 하자.
function getCases(opers: string[]): Set<{ [operator: string]: number }> {
const cases = new Set<{ [operator: string]: number }>()
for (let i = 0; i < opers.length; i++)
for (let j = 0; j < opers.length; j++)
for (let k = 0; k < opers.length; k++)
if (i !== j && j !== k && i !== k) {
cases.add({ '*': i, '-': j, '+': k })
}
return cases
}
const postFix = (
splittedExp: string[],
operator: { [operator: string]: number }
): number => {
const stack: string[] = []
const result: (string | number)[] = []
splittedExp.forEach(elem => {
const parsedElem = parseInt(elem)
if (!Number.isNaN(parsedElem)) {
result.push(parsedElem)
} else {
// *|+|-
while (stack.length) {
if (operator[elem] <= operator[stack[stack.length - 1]]) {
result.push(stack.pop())
} else {
break
}
}
stack.push(elem)
}
})
while (stack.length) {
result.push(stack.pop())
}
const numStack: number[] = []
result.forEach(elem => {
if (typeof elem == 'number') {
numStack.push(elem)
} else {
const num2: number = numStack.pop()
const num1: number = numStack.pop()
switch (elem) {
case '+':
numStack.push(num1 + num2)
break
case '-':
numStack.push(num1 - num2)
break
case '*':
numStack.push(num1 * num2)
break
}
}
})
return numStack[0]
}
function solution(expression: string): number {
const operators = ['*', '+', '-']
const cases = getCases(operators)
const splittedExp = expression.split(/(\*|\-|\+)/)
let max = 0
cases.forEach(element => {
const result = Math.abs(postFix(splittedExp, element))
max = max < result ? result : max
})
return max
}
export default solution